using System;
using System.IO;
using System.Net.Mail;
using System.Text;
using System.Net.Mime;
using System.Net;
using System.Configuration;
using System.Collections.Specialized;

namespace ECommerce.Library.Mail
{
    public class MailSender
    {
        #region Method Comments
        /*****************************************************
         * Purpose: 
         * Sends a SMTP mail. Exceptions are rethrown.
         * 
         * Created By: Jalal
         * 
         * **************************************************/
        #endregion
        private static bool SendMail(MailSettings mailSettings, NameWithEmail sender, NameWithEmail[] receivers, NameWithEmail[] ccList,
            NameWithEmail[] bccList, string subject, string body, MailTypeOptions mailType, string[] attachments,
            NameWithEmail replyTo, DeliveryNotificationOptions notificationOption, MailPriority priority, 
            MailImage[] mailImages)
        {

            body = String.IsNullOrEmpty(body) ? String.Empty : body;
            subject = String.IsNullOrEmpty(subject) ? String.Empty : subject;

            try
            {
                MailMessage mail = new MailMessage();
                mail.From = new MailAddress(sender.EmailAddress, sender.Name, Encoding.UTF8);
                mail.Sender = new MailAddress(sender.EmailAddress, sender.Name, Encoding.UTF8);
                mail.Subject = subject ;
                mail.SubjectEncoding = Encoding.UTF8;
                mail.Priority = priority;
                mail.ReplyTo = new MailAddress(replyTo.EmailAddress, replyTo.Name, Encoding.UTF8);
                mail.DeliveryNotificationOptions = notificationOption;

                if (mailType == MailTypeOptions.HTMLMail)
                {
                    mail.IsBodyHtml = true;
                    mail.Body = body;
                }
                else if (mailType == MailTypeOptions.HTMLWithImageMail)
                {
                    AlternateView alternateView = AlternateView.CreateAlternateViewFromString(body, Encoding.UTF8,
                        MediaTypeNames.Text.Html);
                    foreach (MailImage mailImage in mailImages)
                    {
                        FileInfo fileInfo = new FileInfo(mailImage.FileName);
                        string extension = fileInfo.Extension.ToLower();
                        LinkedResource linkedResource;
                        if(extension=="jpg" || extension=="jpeg")
                            linkedResource = new LinkedResource(mailImage.FileName,MediaTypeNames.Image.Jpeg);
                        else if(extension=="gif")
                            linkedResource = new LinkedResource(mailImage.FileName,MediaTypeNames.Image.Gif);
                        else if(extension=="tiff")
                            linkedResource = new LinkedResource(mailImage.FileName,MediaTypeNames.Image.Tiff);
                        else
                            linkedResource = new LinkedResource(mailImage.FileName, MediaTypeNames.Image.Jpeg);

                        linkedResource.ContentId = mailImage.ContentId;
                        alternateView.LinkedResources.Add(linkedResource);

                    }
                    string alternateText = "You must use an e-mail client that supports HTML message to view the content of this mail";
                    AlternateView alternateTextView = AlternateView.CreateAlternateViewFromString(alternateText, 
                        null, MediaTypeNames.Text.Plain);
                    mail.AlternateViews.Add(alternateTextView);

                }
                else
                {
                    mail.Body = body;
                }
                
                if (receivers != null && receivers.Length > 0)
                {
                    foreach (NameWithEmail receiver in receivers)
                    {
                        mail.To.Add(new MailAddress(receiver.EmailAddress, receiver.Name, Encoding.UTF8));
                    }
                }
                if (ccList != null && ccList.Length > 0)
                {
                    foreach (NameWithEmail cc in ccList)
                    {
                        mail.CC.Add(new MailAddress(cc.EmailAddress, cc.Name, Encoding.UTF8));
                    }
                }
                if (bccList != null && bccList.Length > 0)
                {
                    foreach (NameWithEmail bcc in bccList)
                    {
                        mail.Bcc.Add(new MailAddress(bcc.EmailAddress, bcc.Name, Encoding.UTF8));
                    }
                }
                if (attachments != null && attachments.Length > 0)
                {
                    foreach (string attachment in attachments)
                    {
                        if( !String.IsNullOrEmpty( attachment ) )
                            mail.Attachments.Add(new Attachment(attachment, MediaTypeNames.Application.Octet));
                    }
                }
                
                SmtpClient smtpClient;
                if ( mailSettings.Port > 0 )
                {
                    smtpClient = new SmtpClient( mailSettings.ServerAddress, mailSettings.Port );
                }
                else
                {
                    smtpClient = new SmtpClient( mailSettings.ServerAddress );
                }
                smtpClient.UseDefaultCredentials = true;
                smtpClient.EnableSsl = mailSettings.UseSSL;

                if(!String.IsNullOrEmpty(mailSettings.UserName))
                    smtpClient.Credentials = new NetworkCredential( mailSettings.UserName, 
                        mailSettings.Password );

                smtpClient.Send( mail );
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static bool SendTemplatedMaill(MailSettings mailSettings, string templatePath,
            NameValueCollection items)
        {
            if (String.IsNullOrEmpty(mailSettings.AdminMail) || String.IsNullOrEmpty(mailSettings.SupportMail)
                || String.IsNullOrEmpty(items["ReceiverName"]) || String.IsNullOrEmpty(items["ReceiverEmail"]))
                throw new ArgumentNullException("Sender and receiver mail addess should not be empty");

            try
            {
                FileInfo fileInfo = new FileInfo(AppDomain.CurrentDomain.BaseDirectory + templatePath);
                if (fileInfo.Exists)
                {
                    string mailBody = File.ReadAllText(fileInfo.FullName);
                    string[] attachments = new string[0];
                    string subject = items["Subject"];
                    StringBuilder body = new StringBuilder(mailBody);

                    foreach (string key in items.AllKeys)
                    {
                        body = body.Replace(key, items[key]);
                    }

                    //NameWithEmail sender = new NameWithEmail(items["Sender"], mailSettings.AdminMail);
                    NameWithEmail sender = new NameWithEmail(mailSettings.SenderName, mailSettings.AdminMail);
                    NameWithEmail reply = new NameWithEmail(items["<Support>"], mailSettings.SupportMail);
                    NameWithEmail[] receiver = new NameWithEmail[] { new NameWithEmail(items["ReceiverName"], 
                        items["ReceiverEmail"]) };
                    NameWithEmail[] ccList = new NameWithEmail[0];
                    NameWithEmail[] bccList = new NameWithEmail[0];

                    MailTypeOptions mailType = MailTypeOptions.HTMLMail;
                    DeliveryNotificationOptions deliveryOptions = DeliveryNotificationOptions.OnFailure;
                    MailPriority priority = MailPriority.High;
                    MailImage[] images = new MailImage[0];

                    return SendMail(mailSettings, sender, receiver, ccList, bccList, subject, body.ToString(), 
                        mailType, attachments, reply, deliveryOptions, priority, images);

                }
                else
                    throw new IOException("Mail template file not found");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static bool SendHtmlMaill( MailSettings mailSettings, string mailText, NameValueCollection items )
        {
            if (String.IsNullOrEmpty(mailSettings.AdminMail) || String.IsNullOrEmpty(mailSettings.SupportMail)
                || String.IsNullOrEmpty(items["ReceiverName"]) || String.IsNullOrEmpty(items["ReceiverEmail"]))
                throw new ArgumentException("Sender and receiver mail addess should not be empty");

            try
            {

                if ( mailText != null )
                {
          
                    string[] attachments = new string[0];
                    string subject = items["Subject"];

                    //NameWithEmail sender = new NameWithEmail(items["Sender"], mailSettings.AdminMail);
                    NameWithEmail sender = new NameWithEmail(mailSettings.SenderName, mailSettings.AdminMail);
                    NameWithEmail reply = new NameWithEmail(items["<Support>"], mailSettings.SupportMail);
                    NameWithEmail[] receiver = new NameWithEmail[] { new NameWithEmail(items["ReceiverName"], 
                        items["ReceiverEmail"]) };
                    NameWithEmail[] ccList = new NameWithEmail[0];
                    NameWithEmail[] bccList = new NameWithEmail[0];

                    MailTypeOptions mailType = MailTypeOptions.HTMLMail;
                    DeliveryNotificationOptions deliveryOptions = DeliveryNotificationOptions.OnFailure;
                    MailPriority priority = MailPriority.High;
                    MailImage[] images = new MailImage[0];

                    return SendMail(mailSettings, sender, receiver, ccList, bccList, subject, mailText,
                        mailType, attachments, reply, deliveryOptions, priority, images);

                }
                else
                    throw new ArgumentNullException("Mail text is null");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// This method is used to test mail functionality. It Tries to send a basic mail to a perticular 
        /// address
        /// </summary>
        /// <param name="sendToEmail">The email address where to send the mail</param>
        /// <returns></returns>
        public static bool SendTestMaill(MailSettings mailSettings, string sendToMail)
        {
            if (String.IsNullOrEmpty(sendToMail))
                throw new ArgumentException("sendToMail should be given");

            try
            {
                string[] attachments = new string[0];
                string subject = "Test Mail";
                string mailText = "This is a test mail";

                NameWithEmail sender = new NameWithEmail("Library - MailSender", "test@test.com");
                NameWithEmail reply = new NameWithEmail("Library - MailSender", "test@test.com");
                NameWithEmail[] receiver = new NameWithEmail[] { new NameWithEmail("Test Account", 
                    sendToMail) };
                NameWithEmail[] ccList = new NameWithEmail[0];
                NameWithEmail[] bccList = new NameWithEmail[0];

                MailTypeOptions mailType = MailTypeOptions.TextMail;
                DeliveryNotificationOptions deliveryOptions = DeliveryNotificationOptions.OnFailure;
                MailPriority priority = MailPriority.High;
                MailImage[] images = new MailImage[0];

                return SendMail(mailSettings, sender, receiver, ccList, bccList, subject, mailText,
                    mailType, attachments, reply, deliveryOptions, priority, images);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}